package com.cxy.common.request;

import android.content.Context;
import android.util.ArrayMap;

import com.fy.baselibrary.retrofit.RequestUtils;
import com.fy.baselibrary.retrofit.RxHelper;
import com.fy.baselibrary.retrofit.ServerException;
import com.fy.baselibrary.retrofit.load.LoadOnSubscribe;

import org.jetbrains.annotations.NotNull;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;

/**
 * description 网络请求 工具类
 * 只封装了 get post，其它的类型请求 put delete 等 自行封装
 * Created by fangs on 2020/6/22 11:47.
 */
public class HttpUtils {

    /**
     *  获取get 请求 被观察者，最终返回数据是 一个对象
     * @param ctx
     * @param clazz     请求完成后 返回数据对象
     * @param apiUrl    请求Url
     * @param params    请求参数
     */
    public static <T> Observable<T> httpGet(Context ctx, Class<T> clazz, String apiUrl, ArrayMap<String, Object> params) {
        if (null == params) params = new ArrayMap<>();
        return RequestUtils.create(ApiService.class)
                .getCompose(apiUrl, params)
                .compose(RxHelper.bindToLifecycle(ctx))
                .compose(RxHelper.handleObj(clazz));
    }

    //获取 json格式 的 post 请求被观察者
    public static <T> Observable<T> httpPost(Context ctx, Class<T> clazz, String apiUrl, ArrayMap<String, Object> params) {
        if (null == params) params = new ArrayMap<>();
        return RequestUtils.create(ApiService.class)
                .postCompose(apiUrl, params)
                .compose(RxHelper.bindToLifecycle(ctx))
                .compose(RxHelper.handleObj(clazz));
    }

    //获取 表单格式 post 请求被观察者
    public static <T> Observable<T> httpPostForm(Context ctx, Class<T> clazz, String apiUrl, ArrayMap<String, Object> params) {
        if (null == params) params = new ArrayMap<>();
        return RequestUtils.create(ApiService.class)
                .postFormCompose(apiUrl, params)
                .compose(RxHelper.bindToLifecycle(ctx))
                .compose(RxHelper.handleObj(clazz));
    }


    /**
     *  获取get 请求 被观察者，最终返回数据是 list
     * @param ctx
     * @param clazz     请求完成后 返回数据对象
     * @param apiUrl    请求UIrl
     * @param params    请求参数
     */
    public static <T> Observable<List<T>> httpGetList(Context ctx, Class<T> clazz, String apiUrl, ArrayMap<String, Object> params) {
        if (null == params) params = new ArrayMap<>();
        return RequestUtils.create(ApiService.class)
                .getCompose(apiUrl, params)
                .compose(RxHelper.bindToLifecycle(ctx))
                .compose(RxHelper.handleList(clazz))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    //获取 json格式 的 post 请求被观察者
    public static <T> Observable<List<T>> httpPostList(Context ctx, Class<T> clazz, String apiUrl, ArrayMap<String, Object> params) {
        return RequestUtils.create(ApiService.class)
                .postCompose(apiUrl, params)
                .compose(RxHelper.bindToLifecycle(ctx))
                .compose(RxHelper.handleList(clazz))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    //获取 表单格式 post 请求被观察者
    public static <T> Observable<List<T>> httpPostFormList(Context ctx, Class<T> clazz, String apiUrl, ArrayMap<String, Object> params) {
        return RequestUtils.create(ApiService.class)
                .postFormCompose(apiUrl, params)
                .compose(RxHelper.bindToLifecycle(ctx))
                .compose(RxHelper.handleList(clazz))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }



//    //get 请求 返回 HTML格式数据
//    public static Observable<Document> getHtmlBody(Context ctx, String apiUrl, ArrayMap<String, Object> params) {
//        return RequestUtils.create(ApiService.class)
//                .getHtmlBody(apiUrl, params)
//                .compose(RxHelper.bindToLifecycle(ctx))
//                .subscribeOn(Schedulers.io())
//                .observeOn(AndroidSchedulers.mainThread());
//    }



    /**
     * 1、多文件上传接口，上传多文件 和 单文件；
     * 2、单文件上传接口，上传单文件
     * @param <T>    返回的数据 泛型
     * @param <R>    上传文件 类型【文件路径 string 或 文件 file】
     * @param clazz  返回的数据对象
     * @param apiUrl 上传文件地址
     * @param files  上传文件数组
     */
    public static <T, R> Observable<Object> uploadFile(Context ctx, Class<T> clazz, String apiUrl,
                                                       final ArrayMap<String, Object> params,
                                                       @NotNull  R... files){
        List<R> data = Arrays.asList(files);

        return Observable.just(data)
                .flatMap(new Function<List<R>, ObservableSource<Object>>() {
                    @Override
                    public synchronized ObservableSource<Object> apply(@NotNull List<R> dataPath) throws Exception {
                        ArrayMap<String, Object> finalParams;
                        if (null == params) {
                            finalParams = new ArrayMap<>();
                        } else {
                            finalParams = new ArrayMap<>(params);
                        }

                        R item = dataPath.get(0);
                        if (item instanceof String)finalParams.put("filePathList", dataPath);
                        else if (item instanceof File)finalParams.put("files", dataPath);
                        else return Observable.error(new ServerException("文件类型错误", -11));

                        LoadOnSubscribe loadOnSubscribe = new LoadOnSubscribe();
                        finalParams.put("LoadOnSubscribe", loadOnSubscribe);
                        finalParams.put("uploadFile", "files");
                        finalParams.put("isFileKeyAES", false);
                        Observable<T> uploadFile = RequestUtils.create(ApiService.class)
                                .uploadFile(apiUrl, finalParams)
                                .compose(RxHelper.handleObj(clazz));

                        return Observable.merge(Observable.create(loadOnSubscribe), uploadFile)
                                .subscribeOn(Schedulers.io())
                                .observeOn(AndroidSchedulers.mainThread());
                    }
                })
                .compose(RxHelper.bindToLifecycle(ctx));
    }

    /**
     * 单文件上传接口，上传多文件
     */
    public static <T, R> Observable<Object> uploadFileTwo(Context ctx, Class<T> clazz, String apiUrl,
                                                       final ArrayMap<String, Object> params,
                                                       @NotNull R... files) {
        List<R> data = Arrays.asList(files);

        ArrayMap<String, Object> finalParams;
        if (null == params) {
            finalParams = new ArrayMap<>();
        } else {
            finalParams = new ArrayMap<>(params);
        }

        finalParams.put("uploadFile", "file");

        return Observable.just(data)
                .flatMap(new Function<List<R>, ObservableSource<R>>() {
                    @Override
                    public ObservableSource<R> apply(@NonNull List<R> rs) throws Exception {
                        long sumLeng = 0L;
                        File file;
                        for (int i = 0; i < rs.size(); i++){
                            R r = rs.get(i);
                            if (r instanceof File) file = (File) r;
                            else if (r instanceof String) file = new File((String) r);//访问手机端的文件资源，保证手机端sdcdrd中必须有这个文件
                            else break;

                            sumLeng += file.length();
                        }

                        LoadOnSubscribe loadOnSubscribe = new LoadOnSubscribe();
                        loadOnSubscribe.setmSumLength(sumLeng);
                        finalParams.put("LoadOnSubscribe", loadOnSubscribe);

                        return Observable.fromIterable(rs);
                    }
                })
                .flatMap(new Function<R, ObservableSource<?>>() {
                    @Override
                    public ObservableSource<?> apply(@NonNull R item) throws Exception {
                        List<R> dataPath = new ArrayList<>();
                        dataPath.add(item);

                        if (item instanceof String)finalParams.put("filePathList", dataPath);
                        else if (item instanceof File)finalParams.put("files", dataPath);
                        else return Observable.error(new ServerException("文件类型错误", -11));

                        Observable<T> uploadFile = RequestUtils.create(ApiService.class)
                                .uploadFile(apiUrl, finalParams)
                                .compose(RxHelper.handleObj(clazz));

                        LoadOnSubscribe loadOnSubscribe = (LoadOnSubscribe) finalParams.get("LoadOnSubscribe");
                        return Observable.merge(Observable.create(loadOnSubscribe), uploadFile)
                                .subscribeOn(Schedulers.io())
                                .observeOn(AndroidSchedulers.mainThread());
                    }
                })
                .compose(RxHelper.bindToLifecycle(ctx));
    }


    //获取 表单格式 post 请求被观察者
//    public static <T> Observable<T> uploadFileForm(Context ctx, Class<T> clazz, String apiUrl, ArrayMap<String, Object> params, Map<String, String> files) {
//
//        String fileJson = files.get("fileList");
//        List<String> media = JSON.parseArray(fileJson, String.class);
//
//        MultipartBody.Part[] parts = new MultipartBody.Part[Objects.requireNonNull(media).size()];
//        int cnt = 0;
//        for (String m : Objects.requireNonNull(media)) {
//            File file = new File(m);
//            RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), file);
//            MultipartBody.Part filePart = MultipartBody.Part.createFormData("files", file.getName(), requestFile);
//            parts[cnt] = filePart;
//            cnt++;
//        }
//        HashMap map = new HashMap<String, RequestBody>();
//        Iterator<Map.Entry<String, Object>> iterator = params.entrySet().iterator();
//        while (iterator.hasNext()) {
//            Map.Entry<String, Object> entry = iterator.next();
//            map.put(entry.getKey(),RequestBody.create(MediaType.parse("text/plain"), entry.getValue().toString()));
//            System.out.println(entry.getKey());
//            System.out.println(entry.getValue());
//        }
//
//        return RequestUtils.create(ApiService.class)
//                .upload(map,parts)
//                .compose(RxHelper.bindToLifecycle(ctx))
//                .compose(RxHelper.handleObj(clazz));
//    }

}
